package com.fandou.base.ui.activity;

import android.app.Activity;
import android.app.Application;
import android.content.pm.ApplicationInfo;
import android.graphics.Color;
import android.os.Bundle;
import android.util.SparseArray;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.DrawableRes;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil;
import androidx.databinding.ViewDataBinding;
import androidx.lifecycle.ViewModelProvider;

import com.blankj.utilcode.util.BarUtils;
import com.fandou.base.BR;
import com.fandou.base.BaseAPP;
import com.fandou.base.R;
import com.fandou.base.ui.BaseUI;
import com.fandou.base.ui.DataBindingConfig;
import com.fandou.base.ui.callback.SharedViewModel;
import com.fandou.base.view.LoadingView;

/**
 * Created by yzj on 2018/12/1.
 */

public abstract class BaseActivity extends AppCompatActivity implements BaseUI {

    protected LoadingView mLoadingView;

    private SharedViewModel mSharedViewModel;

    private ViewModelProvider.Factory mFactory;

    private ViewDataBinding mBinding;

    private TextView mTvStrictModeTip;

    protected abstract void initViewModel();

    protected abstract DataBindingConfig getDataBindingConfig();

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mLoadingView = new LoadingView(this);

        BarUtils.setStatusBarColor(this, Color.TRANSPARENT);
        BarUtils.setStatusBarLightMode(this, true);
        mSharedViewModel = getAppViewModelProvider(this).get(SharedViewModel.class);


        initViewModel();
        DataBindingConfig dataBindingConfig = getDataBindingConfig();


        //TODO tip: DataBinding 严格模式：
        // 将 DataBinding 实例限制于 base 页面中，默认不向子类暴露，
        // 通过这样的方式，来彻底解决 视图调用的一致性问题，
        // 如此，视图刷新的安全性将和基于函数式编程的 Jetpack Compose 持平。

        // 如果这样说还不理解的话，详见 https://xiaozhuanlan.com/topic/9816742350 和 https://xiaozhuanlan.com/topic/2356748910

        ViewDataBinding binding = DataBindingUtil.setContentView(this, dataBindingConfig.getLayout());
        binding.setLifecycleOwner(this);

        binding.setVariable(BR.vm, dataBindingConfig.getStateViewModel());
        SparseArray bindingParams = dataBindingConfig.getBindingParams();

        for (int i = 0, length = bindingParams.size(); i < length; i++) {
            binding.setVariable(bindingParams.keyAt(i), bindingParams.valueAt(i));
        }
        mBinding = binding;
    }


    /**
     * TODO tip: 警惕使用。非必要情况下，尽可能不在子类中拿到 binding 实例乃至获取 view 实例。使用即埋下隐患。
     * 目前的方案是在 debug 模式下，对获取实例的情况给予提示。
     * <p>
     * 如果这样说还不理解的话，详见 https://xiaozhuanlan.com/topic/9816742350 和 https://xiaozhuanlan.com/topic/2356748910
     *
     * @return
     */
    protected ViewDataBinding getBinding() {
        if (isDebug() && mBinding != null) {
            if (mTvStrictModeTip == null) {
                mTvStrictModeTip = new TextView(getApplicationContext());
                mTvStrictModeTip.setAlpha(0.5f);
                mTvStrictModeTip.setTextSize(16);
                mTvStrictModeTip.setBackgroundColor(Color.WHITE);
                mTvStrictModeTip.setText(R.string.debug_activity_databinding_warning);
                ((ViewGroup) mBinding.getRoot()).addView(mTvStrictModeTip);
            }
        }
        return mBinding;
    }

    protected ViewModelProvider getAppViewModelProvider(Activity activity) {
        return new ViewModelProvider((BaseAPP) activity.getApplicationContext(),
                getAppFactory(activity));
    }

    private ViewModelProvider.Factory getAppFactory(Activity activity) {
        Application application = checkApplication(activity);
        if (mFactory == null) {
            mFactory = ViewModelProvider.AndroidViewModelFactory.getInstance(application);
        }
        return mFactory;
    }

    private Application checkApplication(Activity activity) {
        Application application = activity.getApplication();
        if (application == null) {
            throw new IllegalStateException("Your activity/fragment is not yet attached to "
                    + "Application. You can't request ViewModel before onCreate call.");
        }
        return application;
    }

    public boolean isDebug() {
        return getApplicationContext().getApplicationInfo() != null &&
                (getApplicationContext().getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
    }

    public SharedViewModel getSharedViewModel() {
        return mSharedViewModel;
    }

    @Override
    public void loading() {
        mLoadingView.loading();
    }

    @Override
    public void loading(String text) {
        mLoadingView.loading(text);
    }

    @Override
    public void endLoading() {
        mLoadingView.endLoading();
    }

    //Loading ////////////////////////////////////////////////////////////

    protected void showLoading(View loadView) {
        loadView.setVisibility(View.VISIBLE);
    }

    protected void hideLoading(View loadView) {
        loadView.setVisibility(View.GONE);
    }

    //Toast //////////////////////////////////////////////////////////////

    protected void showErrorToast(String message) {
        showToast(R.mipmap.toast_icon_error, message);
    }

    protected void showWarnToast(String message) {
        showToast(R.mipmap.toast_icon_warning, message);
    }

    protected void showInfoToast(String message) {
        showToast(R.mipmap.toast_icon_right, message);
    }

    private void showToast(@DrawableRes int iconRes, String message) {
        View view = LayoutInflater.from(this).inflate(R.layout.toast_layout, null, false);
        ImageView iv_icon = (ImageView) view.findViewById(R.id.toast_icon);
        TextView tv_message = (TextView) view.findViewById(R.id.toast_message);

        iv_icon.setImageResource(iconRes);
        tv_message.setText(message);

        Toast toast = new Toast(getApplicationContext());
        toast.setView(view);
        toast.setGravity(Gravity.CENTER, 0, 0);
        toast.setDuration(Toast.LENGTH_SHORT);
        toast.show();
    }


}
